/*
 * ObjectManager.hpp
 *
 *  Created on: Sep 7, 2013
 *      Author: jason
 */

#ifndef OBJECTMANAGER_HPP_
#define OBJECTMANAGER_HPP_

#include <vector>
#include <unordered_map>
#include <SFML/Graphics.hpp>
#include "util.hpp"
#include "../Objects/Object.hpp"
#include "../Objects/Characters.hpp"
#include "../Objects/Treasure.hpp"
#include "TownMode/TriggerArea.hpp"

namespace OForce_Mode {

enum COLLISION_TYPE {NONE, CHARACTER, STATIC};

struct Char_LessThanLayer {
	bool operator()(OForce_Object::Character *a, OForce_Object::Character *b) {
		return (a->getCurrentLayer() < b->getCurrentLayer());
	}
};

struct Object_LessThanLayer {
	bool operator()(OForce_Object::Object *a, OForce_Object::Object *b) {
		return (a->getCurrentLayer() < b->getCurrentLayer());
	}
};
struct Object_LessThanY {
	bool operator()(OForce_Object::Object *a, OForce_Object::Object *b) {
		return (a->getPosition().y < b->getPosition().y);
	}
};

// base class for Object Managers in different modes (e.g. town/battle)
class ObjectManager {
friend class TownMode;
// friend class WorldMode;
// friend class BattleMode;
public:
	ObjectManager() {}
	~ObjectManager();
	int getNumObjects() {return objectMap.size();}
	OForce_Object::Object *getObject(int id);
	OForce_Object::Character *getCharacter(int id);
	int getNumTreasure() {return vTreasure.size();}
	int getNumCharacters() {return vCharacters.size();}
	// Sorts objects by layer for efficient drawing
	void sortObjects();
	void update();
	void drawLayer(int layer);
	void draw();
	OForce_Object::Object *findInteractable(OForce_Object::Character *character,
			float searchDistance = 16.0f);
	bool collisionCheck(OForce_Object::Character *curChar, int characterIndex);
	COLLISION_TYPE collisionCheck(OForce_Object::Character* curChar, float x, float y);
	// If an object collides with another, check to see if it is possible to
	// do a slight adjustment and do that.
	// This allows the character move more naturally around obstacles.
	bool adjustPathAroundCollision(OForce_Object::Character *character,
			OForce_Object::Object* obj);
	// Do A-Star path-finding
	bool findPath(OForce_Object::Character *character,
			std::vector<sf::Vector2f> &path, sf::Vector2f dest);
private:
	std::unordered_map<int, OForce_Object::Object *> objectMap;
	std::vector<OForce_Object::Object *> vObject;
	std::vector<OForce_Object::Treasure *> vTreasure;
	std::vector<OForce_Object::Character *> vCharacters;
	std::vector<OForce_Mode::TriggerArea *> vTrigger;
	std::vector<sf::ConvexShape> collisionPolys;
	std::vector<sf::FloatRect > collisionRects;
}; // class ObjectManager

} // namespace OForce_Mode
#endif /* OBJECTMANAGER_HPP_ */
